package com.zw.cloud.mybatis.plus.db;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.zw.cloud.mybatis.plus.entity.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 可以自动赋值的字段处理
 */
@Slf4j
public abstract class AutoFillHandler implements MetaObjectHandler {

    private static final String CREATE_USER = "createUser";
    private static final String CREATE_TIME = "createTime";
    private static final String CREATE_SYSTEM = "createSystem";
    private static final String ORG_CODE = "orgCode";
    private static final String UPDATE_USER = "updateUser";
    private static final String UPDATE_TIME = "updateTime";
    private static final String UPDATE_SYSTEM = "updateSystem";
    private final Set<String> alwaysSetFields = Set.of(CREATE_TIME,UPDATE_TIME);

    public abstract String getUserId();

    public abstract String getOrgCode();

    public abstract String getCreateSystem();

    @Override
    public void insertFill(MetaObject metaObject) {
        try {
            fillStrategy(metaObject, CREATE_TIME, LocalDateTime.now());
            fillStrategy(metaObject, CREATE_USER, getUserId());
            fillStrategy(metaObject, CREATE_SYSTEM, getCreateSystem());
            fillStrategy(metaObject, ORG_CODE, getOrgCode());
        } catch (Exception e) {
            log.warn("[AutoFillHandler][insertFill]未获取到公共字段信息,", e);
        }
        // 更新相关字段也一起初始化
        this.updateFill(metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        try {
            fillStrategy(metaObject, UPDATE_TIME, LocalDateTime.now());
            fillStrategy(metaObject, UPDATE_USER, getUserId());
            fillStrategy(metaObject, UPDATE_SYSTEM, getCreateSystem());
            fillStrategy(metaObject, ORG_CODE, getOrgCode());

        } catch (Exception e) {
            log.warn("[AutoFillHandler][updateFill]未获取到公共字段信息,", e);
        }
    }

    @Override
    public MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) {
        if (needSkipFillCreateTime(metaObject,fieldName)) {
            return this;
        }
        // 除了创建和修改时间，其他策略均为:如果属性有值则不覆盖,如果填充值为null则不填充

        if (alwaysSetFields.contains(fieldName)) {
            setFieldValByName(fieldName, fieldVal, metaObject);
        } else if (getFieldValByName(fieldName, metaObject) == null) {
            setFieldValByName(fieldName, fieldVal, metaObject);
        }
        return this;
    }


    /**
     * UserInfo 创建时间有值不覆盖
     */
    private boolean needSkipFillCreateTime(MetaObject metaObject,String fieldName){
        if (metaObject.getOriginalObject() instanceof UserInfo) {
            // 创建时间字段，并且字段有值 不填充
            return fieldName.equalsIgnoreCase(CREATE_TIME) && Objects.nonNull(getFieldValByName(fieldName, metaObject));
        }
        return false;
    }

}
